package com.ma.multi_thread;

import java.util.concurrent.Semaphore;

public class T1116 {
    public static void main(String[] args) throws Exception {
        ZeroEvenOdd2 zeo = new ZeroEvenOdd2(5);
        new Thread(() -> {
            try {
                zeo.zero();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "zero").start();
        new Thread(() -> {
            try {
                zeo.even();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "even").start();
        new Thread(() -> {
            try {
                zeo.odd();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "odd").start();
    }

    static interface ZeroEvenOdd {
        public void zero() throws Exception;

        public void even() throws Exception;

        public void odd() throws Exception;
    }

    static class ZeroEvenOdd2 {
        private int n;

        Semaphore semaphore1;
        Semaphore semaphore2;
        Semaphore semaphore3;

        public ZeroEvenOdd2(int n) {
            this.n = n;
            semaphore1 = new Semaphore(1);
            semaphore2 = new Semaphore(0);
            semaphore3 = new Semaphore(0);
        }


        public void zero() throws InterruptedException {
            for (int i = 1; i <= n; i++) {
                semaphore1.acquire();
                System.out.print(0);
                if(i%2==0){
                    semaphore2.release();
                }else{
                    semaphore3.release();
                }
            }

        }


        public void even() throws InterruptedException {
            for (int i = 2; i <= n; i+=2) {
                semaphore2.acquire();
                System.out.print(i);
                semaphore1.release();

            }

        }


        public void odd() throws InterruptedException {
            for (int i = 1; i <= n; i+=2) {
                semaphore3.acquire();
                System.out.print(i);
                semaphore1.release();

            }

        }
    }

    static class ZeroEvenOdd1 implements ZeroEvenOdd {
        private final int n;
        private int flag = 0;

        public ZeroEvenOdd1(int n) {
            this.n = n;
        }

        @Override
        public void zero() {
            for (int i = 0; i < n; i++) {
                synchronized (this) {
                    while (flag != 0) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(0);

                    if ((i & 1) == 0) {
                        flag = 1;
                    } else {
                        flag = 2;
                    }
                    this.notifyAll();
                }
            }
        }

        @Override
        public void even() {
            for (int i = 2; i <= n; i += 2) {
                synchronized (this) {
                    while (flag != 2) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(i);
                    flag = 0;
                    this.notifyAll();

                }
            }
        }

        @Override
        public void odd() {
            for (int i = 1; i <= n; i += 2) {
                synchronized (this) {
                    while (flag != 1) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(i);
                    flag = 0;
                    this.notifyAll();

                }
            }
        }
    }

}
